package utils

import (
	"encoding/binary"
	"errors"
	"fmt"
	"math"
)

var ()

func EncodeCRCBuf(src []byte) []byte {
	crcBuf := make([]byte, 4)
	crc24 := CRC24QBuf(src)
	binary.BigEndian.PutUint32(crcBuf, crc24)
	return append(src, crcBuf...)
}

func DecodeCRCBuf(src []byte) []byte {
	if len(src) <= 4 {
		return nil
	}
	crc24_0 := binary.BigEndian.Uint32(src[len(src)-4:])
	rval := src[:len(src)-4]
	crc24_1 := CRC24QBuf(rval)
	if crc24_0 == crc24_1 {
		return rval
	}
	return nil
}

// / 设置位上的值
// / SetBitValue(0, 2, true) = 二进制(10)
func SetBitValue(ival uint64, bitN byte, bitVal bool) uint64 {
	bitN = bitN - 1
	if bitVal {
		ival = ival | (U64_1 << bitN)
	} else {
		x := (U64_1 << bitN)
		x = x ^ U64_MAX
		ival = ival & x
	}
	return ival
}

/*
**

	bitN 从0开始
	cmpbitVal, newbitVal, 只能是0或者1
	比较低bitN是否为cmpbitval, 如果是则进行设置为newbitval
	changed :true, 表示有修改
*/
func CmpAndSetBitValue(ival uint64, bitN byte, cmpbitVal, newbitVal byte) (changed bool, newval uint64) {
	mask := (U64_1 << bitN)
	r0 := ival & mask // 大于0表示 该位为1, 否则为0
	if r0 > 0 && cmpbitVal == 0 {
		return false, ival
	}

	if r0 == 0 && cmpbitVal != 0 {
		return false, ival
	}

	if newbitVal > 0 {
		ival = ival | mask
	} else {
		x := mask
		x = x ^ U64_MAX
		ival = ival & x
	}
	return true, ival
}

// / 设置位上的值  0:位第一位
// / SetU8BitValue0(0, 1, true) = 二进制(10)
func SetU8BitValue0(ival byte, bitN byte, bitVal bool) byte {
	if bitVal {
		ival = ival | (U8_1 << bitN)
	} else {
		x := (U8_1 << bitN)
		x = x ^ U8_MAX
		ival = ival & x
	}
	return ival
}

func GetU8BitValue0(ival byte, bitN byte) byte {
	rval := ival & (U8_1 << bitN)
	if rval > 0 {
		return 1
	} else {
		return 0
	}
}

// / 设置位上的值  0:位第一位
// / SetBitValue(0, 1, true) = 二进制(10)
func SetBitValue0(ival uint64, bitN byte, bitVal bool) uint64 {
	if bitVal {
		ival = ival | (U64_1 << bitN)
	} else {
		x := (U64_1 << bitN)
		x = x ^ U64_MAX
		ival = ival & x
	}
	return ival
}

// 0:位第一位
func GetBitValue0(ival uint64, bitN byte) byte {
	rval := ival & (U64_1 << bitN)
	if rval > 0 {
		return 1
	} else {
		return 0
	}
}

// 1:位第一位
func GetBitValue(ival uint64, bitN byte) byte {
	// Result := pvByte and (1 shl pvOffset) shr pvOffset;
	bitN = bitN - 1
	rval := ival & (U64_1 << bitN) >> bitN
	return byte(rval)
}

// / <summary>
// /   HEX转成10进制
// /   HEX中不能有字母
// /   0x65036  -> 65036
// / </summary>
func HEX2BCD(val int) (int, error) {
	var i, j, rval int
	i = 0
	rval = 0
	for {
		j = val % 16
		if j > 9 {
			return -1, errors.New(fmt.Sprintf("HEX2BCD: %d 必须小于10", j))
		}

		rval = j*int(math.Trunc(math.Pow(10, float64(i)))) + rval

		// 商
		val = val / 16
		if val == 0 {
			break
		}

		i++
	}
	return rval, nil
}

func HEX2BCDDef(val, def int) int {
	var i, j, rval int
	i = 0
	rval = 0
	for {
		j = val % 16
		if j > 9 {
			return def
		}

		rval = j*int(math.Trunc(math.Pow(10, float64(i)))) + rval

		// 商
		val = val / 16
		if val == 0 {
			break
		}

		i++
	}
	return rval
}
